-- BANDPASS FILTER MODULE
-- PRAGMA standard control signal mapping:
-- FREQUENCY MAPPING
-- clk_100M							=> clk_100M
-- clk_48k							=> clk_48k
-- reset								=> reset
-- PAY ATTENTION:					RESET IS ACTIVE LOW
-- control_in	(0)				=> enable
--					(1)			 	=> UNUSED
--					(5 downto 2)	=> config_select
--					(7 downto 6)	=> UNUSED
--					(15 downto 8)	=> sample_number
--
--	control_out	(3 downto 0)	<= UNUSED
-- 
-- PCM_data_in_right				=> PCM_data_in_right
-- PCM_data_in_left				=> PCM_data_in_left
-- PCM_data_out_right			<= PCM_data_out_right
-- PCM_data_out_left				<= PCM_data_out_left

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;

entity PRM_freq_1 is
port (
	clk_100M					: in std_logic;
	clk_48k					: in std_logic;
	reset 					: in std_logic;
	
	control_in 				: in std_logic_vector(15 downto 0);
	control_out				: out std_logic_vector(3 downto 0);
	
	fft_data_in_re		 	: in std_logic_vector(23 downto 0);
	fft_data_in_im 		: in std_logic_vector(23 downto 0);
	fft_data_out_re 		: out std_logic_vector(23 downto 0);
	fft_data_out_im	 	: out std_logic_vector(23 downto 0)
	);
end entity PRM_freq_1;

--instantiation template
--PR_freq_1 port map(		clk_100M						=>,
--									clk_48k						=>,
--									reset							=>,
--													
--									control_in					=>,
--									control_out					=>,
--													
--									fft_data_in_re				=>,
--									fft_data_in_im				=>,
--									fft_data_out_re			=>,
--									fft_data_out_im			=>
--									);
	
architecture behaviour of PRM_freq_1 is
	--internal control signals
	--valid values for width: 8, 16, 32
	signal width					: std_logic_vector(7 downto 0) := (others => '0');				--start width = 60
	--valid values for position: width*k < 64
	signal position				: std_logic_vector(7 downto 0) := (others => '0');				--position in respect to centre frequency
	constant c_freq				: std_logic_vector(7 downto 0) := "01000000";					--centre_frequency = 64 (middle of spectrum)
	
	signal sample_number			: std_logic_vector(7 downto 0) := (others => '0');
	signal enable					: std_logic := '0';
	signal config_select			: std_logic_vector(3 downto 0) := (others => '0');
begin
	
	sample_number <= control_in(15 downto 8);
	config_select <= control_in(5 downto 2);
	enable <= control_in(0);
	control_out <= "000" & enable;
	
	config_p: process(clk_100M, reset)
	begin
		if reset = '0' then
			position <= (others => '0');
			width <= (others => '0');
		elsif clk_100M'event and clk_100M = '1' then
			case (config_select) is
				when "0000" => position <= "00000000";			--highpass
									width		<= "00111100";			--passband: 4~63 
				when "0001" => position <= "00000000";			--highpass
									width		<= "00001010";			--passband: 53~63
				when "0010" => position <= "00111100";			--lowpass
									width		<= "00000011";			--passband: 0~4 
				when "0011" => position <= "00000011";			--bandpass
									width		<= "00110010";			--passband: 10~60
				when others => position <= "00000000";			--allpass
									width		<= "00111111";			--passband: 0~63 
			end case;
		end if;
	end process;
	
	core_p: process(clk_100M, reset)
	begin
		if reset = '0' then
			fft_data_out_re <= (others => '0');
			fft_data_out_re <= (others => '0');
		elsif clk_100M'event and clk_100M = '1' then
			if enable = '1' then
				if sample_number < 64 then																	--left side (mirror) spectrum
					if sample_number <= c_freq - position - 1 and 									--!line break for readability!
						sample_number >= c_freq - position - 1 - width then						--valid range
						fft_data_out_re <= fft_data_in_re;
						fft_data_out_im <= fft_data_in_im;
					else
						fft_data_out_re <= (others => '0');
						fft_data_out_re <= (others => '0');
					end if;
				else																								--right side (normal) spectrum
					if sample_number >= c_freq + position and sample_number <= c_freq + position + width then		--valid range
						fft_data_out_re <= fft_data_in_re;
						fft_data_out_im <= fft_data_in_im;
					else
						fft_data_out_re <= (others => '0');
						fft_data_out_re <= (others => '0');
					end if;
				end if;
			else
				fft_data_out_re <= fft_data_in_re;
				fft_data_out_im <= fft_data_in_im;
			end if;
		end if;
	end process;

end architecture behaviour;
